#include "MCULEDDriver.h"
#include "MCUConfig.h"
#include "MCUIO.h"

// ������ʾֻ��ȥ��UpdateLED��Ū������ƹⲻͬ��
#define PWMLEDENDABLEMASK (1 << 4)
#define PWMLEDLEVELMASK (0xF)
u8 pwmLightL = 2;
u8 pwmLightR = 2;

#if (MCU_CHIP_JUSHENG == 1)

#define SET_SCLK() \
	HAL_GPIO_WritePin(CLK_PORT, CLK_BYTE, GPIO_PIN_SET)

#define CLR_SCLK() \
	HAL_GPIO_WritePin(CLK_PORT, CLK_BYTE, GPIO_PIN_RESET)

#define SET_DIO() \
	HAL_GPIO_WritePin(DIO_PORT, DIO_BYTE, GPIO_PIN_SET)

#define CLR_DIO() \
	HAL_GPIO_WritePin(DIO_PORT, DIO_BYTE, GPIO_PIN_RESET)


	#if 0
#elif (MCU_CHIP_BYD == 1)
#define SET_DIO() DATAB |= 0x04
#define CLR_DIO() DATAB &= ~0x04
#define SET_SCLK() DATAD |= 0x80
#define CLR_SCLK() DATAD &= ~0x80
#define SET_STB() DATAA |= 0x01
#define CLR_STB() DATAA &= ~0x01
#define INIT_TRIS() \
	TRISB &= ~0x04; \
	TRISD &= ~0x80; \
	TRISA &= ~0x01
#endif
	#endif

#define DEFAULTDATA 0xFF
#if (16 == NBYTES)
unsigned char LEDSegTable[] = {
	DEFAULTDATA, DEFAULTDATA, DEFAULTDATA, DEFAULTDATA, DEFAULTDATA, DEFAULTDATA, DEFAULTDATA, DEFAULTDATA, DEFAULTDATA, DEFAULTDATA, DEFAULTDATA, DEFAULTDATA, DEFAULTDATA, DEFAULTDATA, DEFAULTDATA, DEFAULTDATA};
#endif

short SegValue[] = {
	DISP_0, DISP_1, DISP_2, DISP_3, DISP_4, DISP_5, DISP_6, DISP_7, DISP_8, DISP_9, DISP_A, DISP_b, DISP_C, DISP_d, DISP_E, DISP_F};

void Delay(char ms)
{
	for (; ms > 0; ms--)
		;
}

void DataStart()
{
#if (1 == CHIP_LED_DRIVER_TM1640B)
	SET_DIO();
	Delay(DELAY_TIME);
	SET_SCLK();
	Delay(DELAY_TIME);
	CLR_DIO();
	Delay(DELAY_TIME);
	CLR_SCLK();
	Delay(DELAY_TIME);
#endif
}

void DataEnd()
{
#if (1 == CHIP_LED_DRIVER_TM1640B)
	CLR_SCLK();
	Delay(DELAY_TIME);
	CLR_DIO();
	Delay(DELAY_TIME);
	SET_SCLK();
	Delay(DELAY_TIME);
	SET_DIO();
	Delay(DELAY_TIME);
#endif
}

void DataWrite(unsigned char dat)
{
	unsigned char i;
	for (i = 0; i < 8; i++)
	{
		CLR_SCLK();
		Delay(DELAY_TIME);
		if (dat & 0x1)
		{
			SET_DIO();
		}
		else
		{
			CLR_DIO();
		}
		Delay(DELAY_TIME);
		SET_SCLK();
		dat >>= 1;
	}
	CLR_SCLK();
}

void LEDUpdate(void)
{
	LEDSendAddrDataInc(ADDRESS_BASE, LEDSegTable, NBYTES);
}

void LEDClear(void)
{
	for (int i = 0; i < NBYTES; i++)
	{
		LEDSegTable[i] = 0x00;
	}
	pwmLightL = 0;
	pwmLightR = 0;
	ll_timer_stop(TIMER0);
	ll_timer_stop(TIMER1);
}

void LEDSetAllOnOff(char Color)
{
	for (int i = 1; i <= 25; i++)
	{
		LEDSetLEDOnOrOff(i, Color);
	}
}

bool LEDisOn(unsigned char WhichLED)
{
	char poswhite = 0x0, posblue = 0x0;
	unsigned char valwhite = 0x0, valblue = 0x0;

	switch (WhichLED)
	{
		// l p 4
		// rp 9
	case LED_POINT:
		poswhite = 4;
		valwhite = (1 << 3);
		break; // ��ըͰ�ĵ�
	case LED_POINT1:
		poswhite = 9;
		valwhite = (1 << 3);
		break;
	case LED_AIRFRYER:
		poswhite = 13;
		valwhite = 32;
		break;
	case LED_ROAST:
		poswhite = 11;
		valwhite = 1;
		break;
	case LED_BRIOL:
		poswhite = 12;
		valwhite = 1;
		break;
	case LED_BAKE:
		poswhite = 13;
		valwhite = 1;
		break;
	case LED_PREHEAT:
		poswhite = 13;
		valwhite = 128;
		break;
	case LED_KEEPWARM:
		poswhite = 12;
		valwhite = 128;
		break;
	case LED_PIZZA:
		poswhite = 11;
		valwhite = 128;
		break;
	case LED_DEHYDRATE:
		poswhite = 11;
		valwhite = 64;
		break;
	case LED_TEMPADD:
		poswhite = 12;
		valwhite = 32;
		break;
	case LED_L:
		if (0 != (PWMLEDLEVELMASK & pwmLightL))
		{
			return true;
		}
		else
		{
			return false;
		}
		//		break;
	case LED_R:
		if (0 != (PWMLEDLEVELMASK & pwmLightR))
		{
			return true;
		}
		else
		{
			return false;
		}
		//		break;
	case LED_TIMEADD:
		poswhite = 12;
		valwhite = 64;
		break;
	case LED_TEMPSUB:
		poswhite = 13;
		valwhite = 16;
		break;
	case LED_START:
		poswhite = 12;
		valwhite = 16;
		break;
	case LED_SINCFINISH:
		poswhite = 13;
		valwhite = 8;
		break;
	case LED_SHAKE:
		poswhite = 12;
		valwhite = 8;
		break;
	case LED_DUALCLOCK:
		poswhite = 12;
		valwhite = 4;
		break;
	case LED_POWER:
		poswhite = 13;
		valwhite = 4;
		posblue = 13;
		valblue = 2;
		break;
	case LED_POWER_RED:
		poswhite = 13;
		valwhite = 2;
		posblue = 13;
		valblue = 4;
		break;
	case LED_TIMESUB:
		poswhite = 12;
		valwhite = 2;
		break;
	case LED_TEMP:
		poswhite = 11;
		valwhite = 32;
		break;
	case LED_TIME:
		poswhite = 13;
		valwhite = 64;
		break;
	default:
		break;
	}

	if (0 != (LEDSegTable[poswhite] & valwhite) ||
		0 != (LEDSegTable[posblue] & valblue))
	{
		return true;
	}
	return false;
}

char LeftLEDState = BLACK;
char RightLEDState = BLACK;
char GetRightLEDState()
{
	return RightLEDState;
}

char GetLeftLEDState()
{
	return LeftLEDState;
}

void TurnOnLeftLED(char State)
{
	switch (State)
	{
	case BLACK:
		ll_timer_stop(TIMER1);
		LeftLEDState = BLACK;
		break;
	// case BLUE:

	// 	if (GetLeftLEDState() != BLUE)
	// 	{
	// 		TYPE_LL_TIMER_PWM_CFG pwm_cfg;
	// 		pwm_cfg.pwm_duty = 0x4;
	// 		pwm_cfg.pwm_period = 0x64;
	// 		ll_timer_pwm_mode_config(TIMER1, &pwm_cfg);
	// 		ll_timer_start(TIMER1, LL_TIMER_MODE_SEL_PWM);
	// 		LeftLEDState = WHITE;
	// 	}

	// 	break;
	case WHITE:
		if (GetLeftLEDState() != WHITE)
		{
			TYPE_LL_TIMER_PWM_CFG pwm_cfg;
			pwm_cfg.pwm_duty = 0x4;
			pwm_cfg.pwm_period = 0x64;
			ll_timer_pwm_mode_config(TIMER1, &pwm_cfg);
			ll_timer_start(TIMER1, LL_TIMER_MODE_SEL_PWM);
			LeftLEDState = WHITE;
		}
		break;
	default:
		if (GetLeftLEDState() != WHITE)
		{
			TYPE_LL_TIMER_PWM_CFG pwm_cfg;
			pwm_cfg.pwm_duty = 0x4;
			pwm_cfg.pwm_period = 0x64;
			ll_timer_pwm_mode_config(TIMER1, &pwm_cfg);
			ll_timer_start(TIMER1, LL_TIMER_MODE_SEL_PWM);
			LeftLEDState = WHITE;
		}
		break;
	}
}

void TurnOnRightLED(char State)
{
	switch (State)
	{
	case BLACK:
		ll_timer_stop(TIMER0);
		RightLEDState = BLACK;
		break;
	// case BLUE:
	// 	if (GetRightLEDState() != BLUE)
	// 	{
	// 		TYPE_LL_TIMER_PWM_CFG pwm_cfg;
	// 		pwm_cfg.pwm_duty = 0x4;
	// 		pwm_cfg.pwm_period = 0x64;
	// 		ll_timer_pwm_mode_config(TIMER0, &pwm_cfg);
	// 		ll_timer_start(TIMER0, LL_TIMER_MODE_SEL_PWM);
	// 		RightLEDState = WHITE;
	// 	}

	// 	break;
	case WHITE:
		if (GetRightLEDState() != WHITE)
		{
			TYPE_LL_TIMER_PWM_CFG pwm_cfg;
			pwm_cfg.pwm_duty = 0x4;
			pwm_cfg.pwm_period = 0x64;
			ll_timer_pwm_mode_config(TIMER0, &pwm_cfg);
			ll_timer_start(TIMER0, LL_TIMER_MODE_SEL_PWM);
			RightLEDState = WHITE;
		}
		break;
	default:
	{
		if (GetRightLEDState() != WHITE)
		{
			TYPE_LL_TIMER_PWM_CFG pwm_cfg;
			pwm_cfg.pwm_duty = 0x4;
			pwm_cfg.pwm_period = 0x64;
			ll_timer_pwm_mode_config(TIMER0, &pwm_cfg);
			ll_timer_start(TIMER0, LL_TIMER_MODE_SEL_PWM);
			RightLEDState = WHITE;
		}
	}
	break;
	}
}

void LEDSetLEDOnOrOff(unsigned char WhichLed, char Color)
{
	char poswhite = 0x0, posblue = 0x0;
	unsigned char valwhite = 0x0, valblue = 0x0;
	switch (WhichLed)
	{
	case LED_POINT:
		poswhite = 4;
		valwhite = (1 << 3);
		break;
	case LED_POINT1:
		poswhite = 9;
		valwhite = (1 << 3);
		break;
	case LED_AIRFRYER:
		poswhite = 13;
		valwhite = 32;
		break;
	case LED_ROAST:
		poswhite = 11;
		valwhite = 1;
		break;
	case LED_BRIOL:
		poswhite = 12;
		valwhite = 1;
		break;
	case LED_BAKE:
		poswhite = 13;
		valwhite = 1;
		break;
	case LED_PREHEAT:
		poswhite = 13;
		valwhite = 128;
		break;

	case LED_KEEPWARM:

#if (1 == GS_SOHO)
		poswhite = 11;
		valwhite = 64;
#else
		poswhite = 12;
		valwhite = 128;
#endif

		break;
	case LED_PIZZA:
		poswhite = 11;
		valwhite = 128;
		break;
	case LED_DEHYDRATE:

#if (1 == GS_SOHO)
		poswhite = 12;
		valwhite = 128;
#else
		poswhite = 11;
		valwhite = 64;
#endif

		break;
	case LED_TEMPADD:
		poswhite = 12;
		valwhite = 32;
		break;
	case LED_L:
		if (WHITE == Color)
		{
			// pwmLightL &= ~PWMLEDLEVELMASK;
			pwmLightL = 2;
			// TurnOnLeftLED(WHITE);
		}
		else if (BLUE == Color)
		{
			// pwmLightL &= ~PWMLEDLEVELMASK;
			pwmLightL = 1;
			// TurnOnLeftLED(WHITE);
		}
		else
		{
			pwmLightL = 0;
			// TurnOnLeftLED(BLACK);
		}
		return;
		//		break;
	case LED_R:
		if (WHITE == Color)
		{
			// pwmLightR &= ~PWMLEDLEVELMASK;
			pwmLightR = 2;
			// TurnOnRightLED(WHITE);
		}
		else if (BLUE == Color)
		{
			// pwmLightR &= ~PWMLEDLEVELMASK;
			pwmLightR = 1;
			// TurnOnRightLED(WHITE);
		}
		else
		{
			pwmLightR = 0;
			// TurnOnRightLED(BLACK);
		}
		return;
		//		break;
	case LED_TIMEADD:
		poswhite = 12;
		valwhite = 64;
		break;
	case LED_TEMPSUB:
		poswhite = 13;
		valwhite = 16;
		break;
	case LED_START:
		poswhite = 12;
		valwhite = 16;
		break;
	case LED_SINCFINISH:
		poswhite = 13;
		valwhite = 8;
		break;
	case LED_SHAKE:
		poswhite = 12;
		valwhite = 8;
		break;
	case LED_DUALCLOCK:
		poswhite = 12;
		valwhite = 4;
		break;
#if (1 == EUL_VERSION)
	case LED_POWER_RED:
		poswhite = 13;
		valwhite = 4;
		posblue = 13;
		valblue = 2;
		break;
	case LED_POWER:
		poswhite = 13;
		valwhite = 2;
		posblue = 13;
		valblue = 4;
		break;
#else
	case LED_POWER:
		poswhite = 13;
		valwhite = 4;
		posblue = 13;
		valblue = 2;
		break;
	case LED_POWER_RED:
		poswhite = 13;
		valwhite = 2;
		posblue = 13;
		valblue = 4;
		break;
#endif
	case LED_TIMESUB:
		poswhite = 12;
		valwhite = 2;
		break;
	case LED_TEMP:
		poswhite = 11;
		valwhite = 32;
		break;
	case LED_TIME:
		poswhite = 13;
		valwhite = 64;
		break;
	default:
		// avoid bug
		return;
	}
	switch (Color)
	{
	case BLACK:
		LEDSegTable[poswhite] &= ~valwhite;
		LEDSegTable[posblue] &= ~valblue;
		break;
	case BLUE:
		LEDSegTable[poswhite] &= ~valwhite;
		LEDSegTable[posblue] |= valblue;
		break;
	case WHITE:
		LEDSegTable[posblue] &= ~valblue;
		LEDSegTable[poswhite] |= valwhite;
		break;
	default:
		break;
	}
}

void LEDSetDitronDigital(int Val, char base, bool isFillZero)
{
	int Value = Val;
	if (isFillZero)
	{
		for (int i = 0; i < NUM_OF_DITRON; i++)
		{
			unsigned char Num = Value % base;
			Value = Value / base;
			LEDSetSegmentValue(i, (unsigned char)SegValue[Num]);
		}
	}
	else
	{
		for (int i = 0; i < NUM_OF_DITRON; i++)
		{
			unsigned char Num = Value % base;

			if (Value > 0)
			{
				LEDSetSegmentValue(i, (unsigned char)SegValue[Num]);
			}
			else
			{
				LEDSetSegmentValue(i, 0);
			}

			Value = Value / base;
		}
	}
}

void LEDSetSegmentValue(char pos, unsigned char val)
{
	switch (pos)
	{
	case 0:
		LEDSegTable[0x7] &= ~DISP_8;
		LEDSegTable[0x7] |= (val);
		break;
	case 1:
		LEDSegTable[0x8] &= ~DISP_8;
		LEDSegTable[0x8] |= (val);
		break;
	case 2:
		LEDSegTable[0x9] &= ~DISP_8;
		LEDSegTable[0x9] |= (val);
		break;
	case 3:
		LEDSegTable[0xa] &= ~DISP_8;
		LEDSegTable[0xa] |= (val);
		break;
	case 4:
		LEDSegTable[0x6] &= ~DISP_8;
		LEDSegTable[0x6] |= (val);
		break;
	case 5:
		LEDSegTable[0x3] &= ~DISP_8;
		LEDSegTable[0x3] |= (val);
		break;
	case 6:
		LEDSegTable[0x4] &= ~DISP_8;
		LEDSegTable[0x4] |= (val);
		break;
	case 7:
		LEDSegTable[0x5] &= ~DISP_8;
		LEDSegTable[0x5] |= (val);
		break;
	default:
		break;
	}
}

void LEDSetDitronValue(char index, unsigned short val)
{
	LEDSegTable[2 * index + 1] = (val >> 8);
	LEDSegTable[2 * index + 0] = (val & 0xFF);
}

void LEDSendAddrDataInc(unsigned char addr, unsigned char *dat, unsigned char dat_len)
{
	DataStart();
	DataWrite(CFG_DATA_CMD_ADD_INC);
	DataEnd();

	DataStart();
	DataWrite(addr);
	unsigned char Idx = 0;
	for (; Idx < NBYTES; Idx++)
	{
		DataWrite(dat[Idx]);
	}
	DataEnd();

	DataStart();
	DataWrite(0x8F);
	// DataWrite(M_DISP_CTRL_SETTING(1));
	DataEnd();

	if (2 == (pwmLightL & PWMLEDLEVELMASK))
	{
		// pwmLightL |= PWMLEDENDABLEMASK;
		TurnOnLeftLED(WHITE);
	}
	else if (1 == (pwmLightL & PWMLEDLEVELMASK))
	{
		// pwmLightL |= PWMLEDENDABLEMASK;
		TurnOnLeftLED(WHITE);
	}
	else
	{
		TurnOnLeftLED(BLACK);
	}

	if (2 == (pwmLightR & PWMLEDLEVELMASK))
	{
		TurnOnRightLED(WHITE);
		// pwmLightR |= PWMLEDENDABLEMASK;
	}
	else if (1 == (pwmLightR & PWMLEDLEVELMASK))
	{
		TurnOnRightLED(WHITE);
		// pwmLightR |= PWMLEDENDABLEMASK;
	}
	else
	{
		TurnOnRightLED(BLACK);
	}
}
